package org.springframework.context.annotation;

import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * 解析bean所在类的其它属性信息，并且注册bean
 */
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider{
    //用来自动装配的后处理器bean的名字
    public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";

    private BeanDefinitionRegistry registry;

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    /**
     * 扫描包中的bean，并且注册到bean工厂
     * @param basePackages 设置的多个扫描包的路径
     */
    public void doScan(String... basePackages){
        //遍历每一个设置的包路径
        for (String basePackage : basePackages) {
            //扫描该包 获取所有的bean定义对象
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

            //遍历每个bean定义对象 添加一些必须的属性
            for (BeanDefinition candidate : candidates) {
                //解析bean的作用域
                String beanScope = resolveBeanScope(candidate);
                if(StrUtil.isNotEmpty(beanScope)){
                    candidate.setScope(beanScope);
                }

                //生成bean的名称
                String beanName = determineBeanName(candidate);

                //注册bean
                registry.registerBeanDefinition(beanName, candidate);

            }
            //注册处理@Autowired和@Value注解的BeanPostProcessor
            registry.registerBeanDefinition(
                    AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME, new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
        }

    }
    /**
     * 获取bean的作用域
     *
     * @param beanDefinition
     * @return
     */
    private String resolveBeanScope(BeanDefinition beanDefinition) {
        //获取bean所在类上的 scope注解的属性
        Class<?> beanClass = beanDefinition.getBeanClass();
        Scope scope = beanClass.getAnnotation(Scope.class);


        if(scope != null){
            //有设置范围 返回设置的
            return scope.value();
        }

        //返回空
        return StrUtil.EMPTY;
    }


    /**
     * 生成bean的名称
     *
     * @param beanDefinition
     * @return
     */
    private String determineBeanName(BeanDefinition beanDefinition) {
        //获取bean所在类上的 component注解的属性
        Class<?> beanClass = beanDefinition.getBeanClass();
        Component component = beanClass.getAnnotation(Component.class);


        String value = component.value();

        if (StrUtil.isEmpty(value)) {
            //属性为空时 根据类名 生成bean的名字
            value = StrUtil.lowerFirst(beanClass.getSimpleName());
        }

        return value;
    }
}
